package cn.jdemo.juc.thread.ThreadLocal;

import java.util.concurrent.*;

/**
 * @see ThreadLocal#set(Object)
 * @see ThreadLocal#get()
 * @see ThreadLocal#remove()
 * @see ThreadLocal#initialValue()
 *
 * @see Thread#threadLocals 此线程有关的ThreadLocal的ThreadLocalMap值。该映射由ThreadLocal类维护
 *
 */
public class Demo01 {

    public static void main(String[] args) {
        // test01();
        // test02();
        // test03();
        test05();
    }

    /**
     * 输出内容
     * main: null
     * pool-1-thread-3: 252583145
     * pool-1-thread-2: -431996756
     * pool-1-thread-1: -1305455309
     */
    public static void test01() {
        final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        for (int i=0;i<3;i++ ){
            threadFactory.newThread(()->{
                threadLocal.set(ThreadLocalRandom.current().nextInt());
                System.out.println(Thread.currentThread().getName()+": "+threadLocal.get().intValue());
            }).start();
        }
        System.out.println(Thread.currentThread().getName()+": "+threadLocal.get());
    }

    /**
     * 输出内容:由于线程池会复用Thread对象,会造成脏数据_显示调用remove()来清理
     * **************************************
     * pool-1-thread-1: 829723701
     * pool-1-thread-3: -977715208
     * pool-1-thread-2: -1503032420
     * pool-1-thread-4: 2021233308
     * **************************************
     * pool-1-thread-1: 829723701
     * pool-1-thread-2: -1503032420
     * pool-1-thread-1: 829723701
     * pool-1-thread-3: -977715208
     */
    public static void test02() {
        final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();

        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        System.out.println("****************first:set并print**********************");
        for (int i=0;i<Runtime.getRuntime().availableProcessors();i++ ){
            executorService.submit(()->{
                threadLocal.set(ThreadLocalRandom.current().nextInt());
                System.out.println(Thread.currentThread().getName()+": "+threadLocal.get().intValue());
            });
        }

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("*****************second:print*********************");
        for (int i=0;i<Runtime.getRuntime().availableProcessors();i++ ){
            executorService.submit(()->{
                System.out.println(Thread.currentThread().getName()+": "+threadLocal.get().intValue());
            });
        }
    }

    /**
     * 
     * @see ThreadLocal#set(Object)
     * @see ThreadLocal#createMap(Thread, Object)
     */
    public static void test03() {

        new Thread(()-> {
            System.out.println(Thread.currentThread().getName()+"start");
            ThreadLocal<Integer> threadLocal1 = new ThreadLocal<Integer>();
            ThreadLocal<String> threadLocal2 = new ThreadLocal<String>();
            ThreadLocal<Long> threadLocal3 = new ThreadLocal<Long>();

            System.out.println(Thread.currentThread().getName()+"running...");

            threadLocal1.set(Integer.MAX_VALUE);// 当前线程第一次set时，会调用ThreadLocal#createMap(Thread, Object)方法
            threadLocal2.set("value");
            threadLocal3.set(Long.MAX_VALUE);
            System.out.println(Thread.currentThread().getName()+"end");
        }).start();

    }

    /**
     * ThreadLocalMap与Thread的生命周期是一样长，手动调用threadLocal1#remove(),防止内存泄漏
     */
    public static void test04() {
        new Thread(()-> {
            System.out.println(Thread.currentThread().getName()+"start");
            ThreadLocal<Integer> threadLocal1 = new ThreadLocal<Integer>();

            System.out.println(Thread.currentThread().getName()+"running...");

            threadLocal1.set(Integer.MAX_VALUE);// 当前线程第一次set时，会调用ThreadLocal#createMap(Thread, Object)方法
            System.out.println(Thread.currentThread().getName()+"end");

            threadLocal1.remove();
        }).start();
    }

    /**
     * 输出内容:
     * Thread-1: 2147483647
     * Thread-0: null
     *
     * @see ThreadLocal#initialValue()
     */
    public static void test05() {
        new Thread(()-> {
            ThreadLocal<Integer> threadLocal1 = new ThreadLocal<Integer>();
            System.out.println(Thread.currentThread().getName()+": "+threadLocal1.get());
        }).start();

        new Thread(()-> {
            ThreadLocal<Integer> threadLocal1 = new ThreadLocal<Integer>(){
                @Override
                protected Integer initialValue() {
                    return Integer.MAX_VALUE;
                }
            };
            System.out.println(Thread.currentThread().getName()+": "+threadLocal1.get());
        }).start();
    }
}
